﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;

namespace GenChord
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void BT_OpenList_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFile = new OpenFileDialog();
            openFile.Filter = "XML File|*.xml|All File|*.*";
            openFile.Multiselect = true;
            if (openFile.ShowDialog() == DialogResult.OK)
            {
                TB_Log.Text = "";
                foreach (string fileName in openFile.FileNames)
                {
                    List_Input.Items.Add(fileName);
                }

                logFile(string.Format("Add {0} files",openFile.FileNames.Length));
            }
        }

        private void BT_Save_Click(object sender, EventArgs e)
        {
            if (List_Input.Items.Count > 0)
            {
                FolderBrowserDialog fbd = new FolderBrowserDialog();
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    logFile(string.Format("Export to {0}", fbd.SelectedPath));
                    readFile(fbd.SelectedPath);
                }
            }
        }

        private void readFile(string folder)
        {
            string sJson = "";
            string sJson2 = "";
            try
            {
                for (int i = 0; i < List_Input.Items.Count; i++)
                {
                    List_Input.SelectedIndex = i;

                    var sFile = List_Input.Items[i];
                    logFile(string.Format("Read file {0}", sFile));
                    if (sFile != null)
                    {
                        StreamReader reader = new StreamReader(sFile.ToString());
                        string s = reader.ReadToEnd();
                        reader.Close();
                        reader.Dispose();

                        var obj = ReadData(s);
                        if (obj != null)
                        {
                            if (obj.Apps.Count > 1)
                            {
                                for (int j = 0; j < obj.Apps.Count; j++)
                                {
                                    if (sJson != "") sJson += ",";
                                    if (sJson2 != "") sJson2 += ",";
                                    string xS = GenChord(obj.name, j + 1, obj.Apps[j]);
                                    string sFileSave = obj.name.Replace('/', '.').Replace("#", ".sharp") + "." + (j + 1) + ".svg";
                                    writeFile(folder + "\\" + sFileSave, xS);
                                    sJson += string.Format("\"{0}\":\"{1}\"", obj.name + "." + (j + 1), sFileSave);
                                    sJson2 += string.Format("{{value:\"{0}\",label:\"{1}\",desc:\"{2}\",icon:\"{3}\"}}", obj.name + "." + (j + 1), obj.name + "." + (j + 1), "", sFileSave);
                                }
                            }
                            else
                            {
                                if (sJson != "") sJson += ",";
                                if (sJson2 != "") sJson2 += ",";
                                string xS = GenChord(obj.name, 0, obj.Apps[0]);
                                string sFileSave = obj.name.Replace('/', '.').Replace("#", ".sharp") + ".svg";
                                writeFile(folder + "\\" + sFileSave, xS);
                                sJson += string.Format("\"{0}\":\"{1}\"", obj.name, sFileSave);
                                sJson2 += string.Format("{{value:\"{0}\",label:\"{1}\",desc:\"{2}\",icon:\"{3}\"}}", obj.name, obj.name, "", sFileSave);
                            }

                        }
                    }
                }
            }
            catch (Exception e)
            {
                logFile(string.Format("Read file error. msg: {0}", e.Message));
            }
            finally
            {
                string sx = string.Format("var GuitarChord = {{{0}}};var GuitarShow = [{1}];", sJson, sJson2);
                StreamWriter writer = new StreamWriter(folder + "\\GuitarChordLib.js");
                writer.Write(sx);
                writer.Close();
                writer.Dispose();
                logFile(string.Format("sucsess!"));
            }
        }

        private static void writeFile(string sFile, string sContent)
        {
            StreamWriter writer = new StreamWriter(sFile, false);
            writer.Write(sContent);
            writer.Close();
            writer.Dispose();
        }

        public static string GenChord(string name, int iVer, app oApp)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<svg width=\"460\" height=\"480\" xmlns=\"http://www.w3.org/2000/svg\">");
            sb.Append("<defs>" +
                      "<linearGradient y2=\"0.5\" x2=\"1\" y1=\"0.5\" x1=\"0\" id=\"FillStyle1\">" +
                      "<stop stop-color=\"#1A1711\" offset=\"0\"/>" +
                      "<stop stop-color=\"#E0C493\" offset=\"0.45\"/>" +
                      "<stop stop-color=\"#FFEECE\" offset=\"0.55\"/>" +
                      "<stop stop-color=\"#1A1711\" offset=\"1\"/>" +
                      "</linearGradient>" +
                      "<linearGradient id=\"FillStyle2\" x1=\"1\" y1=\"2\" x2=\"1\" y2=\"-1\">" +
                      "<stop offset=\"0.2332\" stop-color=\"#878D8F\"/>" +
                      "<stop offset=\"0.6666\" stop-color=\"#E0E0E0\"/>" +
                      "<stop offset=\"0.8764\" stop-color=\"#8B9298\"/>" +
                      "<stop offset=\"1\" stop-color=\"#D1D3D4\"/>" +
                      "</linearGradient>" +
                      "</defs>");
            sb.AppendFormat("<g><title>Chord {0}</title>", name + (iVer > 0 ? "." + iVer.ToString() : ""));
            sb.Append("<rect x=\"0\" y=\"60\" width=\"460\" height=\"340\" fill=\"#1B1813\"/>");

            //dọc
            int iV = 78;
            for (int i = 5; i >= 0; i--)
                sb.AppendFormat("<rect x=\"{0}\" y=\"65\" width=\"10\" height=\"330\" fill=\"url(#FillStyle1)\"/>  ", 40 + i * iV);

            //ngang
            int iH = 55;
            for (int i = 5; i >= 0; i--)
            {
                //ngang
                double dH = 8 - i;
                if (dH == 5) dH = 6.5;
                if (dH == 4) dH = 5;
                if (dH == 3) dH = 4;
                sb.AppendFormat("<rect x=\"0\" y=\"{0}\" width=\"460\" height=\"{1}\" fill=\"url(#FillStyle2)\"/>", 90 + i * iH, dH.ToString().Replace(',','.'));
                //phải
                if (oApp.ListS[5 - i] == -1)
                    sb.AppendFormat("<text x=\"450\" y=\"{0}\" stroke-width=\"2\" stroke=\"#FFF\" fill=\"#084C80\" font-family=\"Sans-serif\" font-size=\"25\" font-weight=\"bold\" text-anchor=\"middle\">X</text>", 102 + i * iH - i / 2);
                else
                    sb.AppendFormat("<circle cx=\"450\" cy=\"{0}\" r=\"7\" fill=\"#084C80\" stroke=\"#FFFFFF\" stroke-width=\"4\"/> ", 95 + i * iH - i / 2);
                //trái
                sb.AppendFormat("<circle fill=\"#084C80\" stroke=\"#FFFFFF\" stroke-width=\"4\" cx=\"20\" cy=\"{0}\" r=\"15\"/>", 95 + i * iH - i / 2);
                string sText = "";
                switch (i)
                {
                    case 0:
                    case 5:
                        sText = "E";
                        break;
                    case 1:
                        sText = "A";
                        break;
                    case 2:
                        sText = "D";
                        break;
                    case 3:
                        sText = "G";
                        break;
                    case 4:
                        sText = "B";
                        break;
                }

                sb.AppendFormat("<text x=\"20\" y=\"{0}\" fill=\"#FFFFFF\" font-family=\"'Arial-BoldMT'\" font-size=\"20\" font-weight=\"bold\" text-anchor=\"middle\">{1}</text>", 102 + i * iH - i / 2, sText);
            }

            //node
            for (int i = 0; i < 4; i++)
            {
                if (oApp.Listf[i].str != 0 && oApp.Listf[i].pos != 0)
                {
                    int cx = 84 + (5 - oApp.Listf[i].pos) * 78;
                    int cy = 93 + (6 - oApp.Listf[i].str) * 55;
                    sb.AppendFormat("<circle fill=\"#054E80\" stroke-width=\"4\" cx=\"{0}\" cy=\"{1}\" r=\"24\" stroke=\"#ffffff\"/>", cx, cy);
                    sb.AppendFormat("<text x=\"{0}\" y=\"{1}\" fill=\"#ffffff\" font-size=\"35\" font-family=\"Sans-serif\" text-anchor=\"middle\" font-weight=\"bold\">{2}</text>", cx, cy + 10, i + 1);

                    //length
                    if (oApp.Listf[i].length > 1)
                    {
                        sb.AppendFormat("<rect fill=\"#054E80\" stroke-width=\"0\" x=\"{0}\" y=\"{1}\" width=\"35\" height=\"{2}\" />", cx - 17, cy + 30, oApp.Listf[i].length * 55 - 30 - 30);//390 - ((oApp.Listf[i].length-1)*60)
                    }
                }
            }

            //ver
            if (iVer > 0)
            {
                sb.Append("<circle r=\"15\" cy=\"31\" cx=\"80\" stroke-width=\"4\" stroke=\"#FFFFFF\" fill=\"#084C80\"/>");
                sb.AppendFormat("<text text-anchor=\"middle\" font-weight=\"bold\" font-size=\"20\" font-family=\"'Arial-BoldMT'\" fill=\"#FFFFFF\" y=\"37.5\" x=\"80\">{0}</text>", iVer);
            }

            //text trên
            sb.AppendFormat("<text y=\"50\" x=\"395\" font-size=\"50\" text-anchor=\"middle\" fill=\"#054E80\" font-family=\"'Arial-BoldMT'\">{0}</text>",ToRoman(int.Parse(oApp.Fret)));

            //chord name
            sb.AppendFormat("<text y=\"460\" x=\"230\" font-size=\"70\" font-weight=\"bold\" text-anchor=\"middle\" fill=\"#074D80\" font-family=\"'Arial-BoldMT'\">{0}</text>", name);
            sb.Append("</g></svg>");
            return sb.ToString();
        }

        public ChordInfo ReadData(string sXML)
        {
            try
            {
                ChordInfo info = new ChordInfo();
                XmlDocument xDoc = new XmlDocument();
                XmlReader reader = XmlReader.Create(new StringReader(sXML));
                xDoc.Load(reader);

                XmlNodeList oID = xDoc.GetElementsByTagName("ID");
                string sRead = oID[0].InnerText;
                info.id = sRead;

                XmlNodeList oName = xDoc.GetElementsByTagName("Name");
                sRead = oName[0].InnerText;
                info.name = sRead;

                List<app> oList = new List<app>();
                XmlNodeList oApps = xDoc.GetElementsByTagName("App");
                for (int i = 0; i < oApps.Count; i++)
                {
                    app item = new app();

                    item.Fret = oApps.Item(i).ChildNodes[0].InnerText;


                    List<Finger> oListF = new List<Finger>();
                    for (int j = 2; j <= 5; j++)
                    {
                        Finger of = new Finger();
                        var of1 = oApps.Item(i).ChildNodes[j];
                        of.str = int.Parse(of1.ChildNodes[0].InnerText);
                        of.pos = int.Parse(of1.ChildNodes[1].InnerText);
                        of.length = int.Parse(of1.ChildNodes[2].InnerText);
                        oListF.Add(of);
                    }
                    item.Listf = oListF;

                    List<int> oListS = new List<int>();
                    for (int j = 6; j <= 11; j++)
                    {
                        oListS.Add(int.Parse(oApps.Item(i).ChildNodes[j].InnerText));
                    }
                    item.ListS = oListS;

                    oList.Add(item);
                }

                info.Apps = oList;
                return info;
            }
            catch (Exception e)
            {
                //MessageBox.Show("Error format file Chord file", "Error", MessageBoxButtons.OK);
                logFile("Error format file Chord file");
                return null;
            }
        }

        public static string ToRoman(int number)
        {
            if (-9999 >= number || number >= 9999)
            {
                throw new ArgumentOutOfRangeException("number");
            }

            if (number == 0)
            {
                return "NULL";
            }

            StringBuilder sb = new StringBuilder(10);

            if (number < 0)
            {
                sb.Append('-'); number *= -1;
            } 
            string[,] table = new string[,] { { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" }, { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" }, { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" }, { "", "M", "MM", "MMM", "M(V)", "(V)", "(V)M", "(V)MM", "(V)MMM", "M(X)" } }; 
            for (int i = 1000, j = 3; i > 0; i /= 10, j--)
            {
                int digit = number / i;
                sb.Append(table[j, digit]);
                number -= digit * i;
            }

            return sb.ToString();
        }

        private void List_Input_SelectedIndexChanged(object sender, EventArgs e)
        {
            return;
            TB_Log.Text = "";

            var sFile = List_Input.SelectedItem;
            if (sFile != null)
            {
                StreamReader reader = new StreamReader(sFile.ToString());
                string s = reader.ReadToEnd();
                TB_Log.Text = s;
                reader.Close();
                reader.Dispose();
            }
        }

        private void BT_Clear_Click(object sender, EventArgs e)
        {
            List_Input.Items.Clear();
            logFile(string.Format("Clear all files"));
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var i = List_Input.SelectedIndex;
            if (i != null && i >= 0) List_Input.Items.RemoveAt(i);
            logFile(string.Format("Delete ok!"));
        }

        private void logFile(string s)
        {
            TB_Log.Text +=string.Format(" - {0:HH:mm:ss dd/MM/yyyy}: ",DateTime.Now) + s + "\r\n";
        }
    }
}
